﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace TiposComuns.Objectos
{
    /// <summary>
    /// Contains the identification of a person, namely it's username and URI
    /// </summary>
    [Serializable]
    public class Person
    {
        #region Attributes
        private byte[] hash;
        private string username;
        #endregion

        #region Constructor
        public Person()
        {
            this.hash = new byte[TiposComuns.Objectos.HashService.NBITS];
            this.Address = new Address("",0);
            this.username = "";
        }

        public Person(string username, Address address)
        {
            this.Username = username;
            this.Address = address;
            //this.hash = new byte[TiposComuns.Objectos.HashService.NBITS];
            this.hash = TiposComuns.Objectos.HashService.CalculateHash(username);
        }
        #endregion

        #region gets e sets

        /// <summary>
        /// Username
        /// </summary>
        public string Username
        {
            get { return username; }
            set { this.username = value; this.hash = TiposComuns.Objectos.HashService.CalculateHash(value); }
        }

        

        /// <summary>
        /// Address of the user's servers
        /// </summary>
        public Address Address
        {
            get;
            set;
        }

        /// <summary>
        /// Time of the last contact made with this person
        /// </summary>
        public DateTime LastAccess
        {
            get;
            set;
        }
        
        public byte[] Hash
        {
            get { return hash; }
            set { hash = value; }
        }
        
        #endregion

        #region Methods
        /// <summary>
        /// Determines the bitth bit of the hash
        /// </summary>
        /// <param name="bit">bit order</param>
        /// <returns>bit</returns>
        public int GetBit(int bit)
        {
            bit = HashService.NBITS - bit - 1;

            int index = bit / TiposComuns.Objectos.HashService.NBITS;
            bit -= TiposComuns.Objectos.HashService.NBITS * index;

            int i;
            for (i = 0; i < index && hash[i] == 0 ; i++) ;
            

            if (i < index)
                return 1;

            byte aux = (byte)(7 - bit);
            byte mask_g = (byte)(1 << aux);          //Mask for retrieving the bit


            return (mask_g & hash[i]) >> aux;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            
            byte bit = hash[0];
            for (int i = 0; i < TiposComuns.Objectos.HashService.NBITS; i++)
            {                
                sb.Append(bit>>7);
                bit <<= 1;
            }

            return sb.ToString();
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (obj.GetType() != this.GetType()) return false;
            Person p = (Person)obj;

            return p.username.Equals(this.username);
        }

        public Person Clone()
        {
            return new Person(this.username, this.Address.Clone());           
        }
        #endregion
    }
}
